﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZedGraph;
using System.Drawing;

namespace NumMethods_HW1_HeatEquation
{
    class HeatEquation
    {
        private double tPeriod;
        private double xLeftCoordinate;
        private double xRightCoordinate;
        private int xNumParts;
        private int tNumParts;

        private double[,] Temperature;

        double stepX;
        double stepT;

        private double[] xCoordinates;
        private double[] timePeriods;

        public HeatEquation(int xNumParts, int tNumParts, double xLeft, double xRight, double T)
        {
            this.xNumParts = xNumParts;
            this.tNumParts = tNumParts;
            Temperature = new double[xNumParts + 1, tNumParts + 1];
            xCoordinates = new double[xNumParts + 1];
            timePeriods = new double[tNumParts + 1];

            xLeftCoordinate = xLeft;
            xRightCoordinate = xRight;
            tPeriod = T;

            stepX = (xRightCoordinate - xLeftCoordinate) / xNumParts;
            stepT = tPeriod / tNumParts;

            for (int ix = 0; ix <= xNumParts; ix++)
                xCoordinates[ix] = xLeftCoordinate + ix * stepX;

            for (int it = 0; it <= tNumParts; it++)
                timePeriods[it] = it * stepT;

            // Border Conditions
            for (int it = 1; it <= tNumParts; it++)
            {
                Temperature[0, it] = leftBorderCondrion(timePeriods[it]);
                Temperature[xNumParts, it] = rightBorderCondition(timePeriods[it]);
            }

            // Initial Conditions
            for (int ix = 0; ix <= xNumParts; ix++)
                Temperature[ix, 0] = initConditions(xCoordinates[ix]);

        }

        public void CalculateTemperature()
        {
            for (int it = 0; it <= (tNumParts - 1); it++)
            {
                for (int ix = 1; ix <= (xNumParts - 1); ix++)
                {
                    Temperature[ix, it + 1] = Temperature[ix, it] +
                        (stepT * (Temperature[ix - 1, it] - 2 * Temperature[ix, it] + Temperature[ix + 1, it]) / Math.Pow(stepX, 2));
                }
            }

        }

        public void DrawGraphic(ZedGraphControl zedGraph, int time)
        {
            GraphPane pane = zedGraph.GraphPane;

            // Изменим текст надписи по оси Х
            pane.XAxis.Title.Text = "X";
            // Изменим текст по оси Y
            pane.YAxis.Title.Text = "V(x,t)";

            pane.CurveList.Clear();

            PointPairList list = new PointPairList();

            for (int ix = 0; ix <= xNumParts; ix++)
                list.Add(xCoordinates[ix], Temperature[ix, time]);

            LineItem temperatureCurve = pane.AddCurve("Temperature", list, Color.Blue, SymbolType.None);

            // Включаем отображение сетки напротив крупных рисок по оси X
            pane.XAxis.MajorGrid.IsVisible = true;

            // Задаем вид пунктирной линии для крупных рисок по оси X:
            // Длина штрихов равна 10 пикселям, ... 
            pane.XAxis.MajorGrid.DashOn = 10;

            // затем 5 пикселей - пропуск
            pane.XAxis.MajorGrid.DashOff = 5;


            // Включаем отображение сетки напротив крупных рисок по оси Y
            pane.YAxis.MajorGrid.IsVisible = true;

            // Аналогично задаем вид пунктирной линии для крупных рисок по оси Y
            pane.YAxis.MajorGrid.DashOn = 10;
            pane.YAxis.MajorGrid.DashOff = 5;


            // Включаем отображение сетки напротив мелких рисок по оси X
            pane.YAxis.MinorGrid.IsVisible = true;

            // Задаем вид пунктирной линии для крупных рисок по оси Y: 
            // Длина штрихов равна одному пикселю, ... 
            pane.YAxis.MinorGrid.DashOn = 1;

            // затем 2 пикселя - пропуск
            pane.YAxis.MinorGrid.DashOff = 2;

            // Включаем отображение сетки напротив мелких рисок по оси Y
            pane.XAxis.MinorGrid.IsVisible = true;

            // Аналогично задаем вид пунктирной линии для крупных рисок по оси Y
            pane.XAxis.MinorGrid.DashOn = 1;
            pane.XAxis.MinorGrid.DashOff = 2;


            zedGraph.AxisChange();
            zedGraph.Invalidate();
        }

        private double leftBorderCondrion(double value)
        {
            return 0;
        }

        private double rightBorderCondition(double value)
        {
            return 0;
        }

        private double initConditions(double value)
        {
            return value;
        }
    }
}
